home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume10 / qterm < prev    next >
Encoding:
Text File  |  1987-07-29  |  24.5 KB  |  1,053 lines

  1. Path: uunet!rs
  2. From: rs@uunet.UU.NET (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v10i072:  Query terminal for its type
  5. Message-ID: <737@uunet.UU.NET>
  6. Date: 30 Jul 87 22:28:17 GMT
  7. Organization: UUNET Communications Services, Arlington, VA
  8. Lines: 1042
  9. Approved: rs@uunet.UU.NET
  10.  
  11. Submitted-by: Michael A. Cooper <mcooper@oberon.usc.edu>
  12. Posting-number: Volume 10, Issue 72
  13. Archive-name: qterm
  14.  
  15. [  This program sends a "what are you" escape sequence to a terminal,
  16.    and interprets the reply.  --r$  ]
  17.  
  18. #!/bin/sh
  19. # This is a shell archive, meaning:
  20. # 1. Remove everything above the #!/bin/sh line.
  21. # 2. Save the resulting text in a file.
  22. # 3. Execute the file with /bin/sh (not csh) to create the files:
  23. #    README
  24. #    Makefile
  25. #    qtermtab
  26. #    qterm.c
  27. #    qterm.h
  28. #    qterm.1
  29. export PATH; PATH=/bin:$PATH
  30. echo shar: extracting "'README'" '(1233 characters)'
  31. if test -f 'README'
  32. then
  33.     echo shar: over-writing existing file "'README'"
  34. fi
  35. cat << \SHAR_EOF > 'README'
  36.  
  37.          Q T E R M  -  Q U E R Y   T E R M I N A L
  38.  
  39.                              $Revision: 3.0 $
  40.                         $Date: 87/06/30 19:14:35 $
  41.  
  42.     Qterm is a program that queries terminals to find out what
  43. kind of terminal is responding.  It is useful to automagically define
  44. your terminal type.  It prints the name of the terminal (compatible,
  45. hopefully, with a termcap/terminfo name) such as "vt100" to standard
  46. output.  See the manual for details.
  47.  
  48.     Qterm was written under 4.2BSD and will probably run without
  49. modification on other Berkeley Unix systems.  It has been tested under
  50. VAX 4.2BSD, VAX 4.3BSD, Sun 3.0 and Sun 3.2.  It is know to work under
  51. System V.2, but I have not personally tested it on such a system.
  52. (For System V.2, compile with USG5 defined).
  53.  
  54.     If you have ARPA Internet access, the latest and greatest
  55. version of qterm is available from oberon.USC.EDU via anonymous ftp in
  56. the file pub/qterm.shar.  I update this file fairly often, so it's
  57. bound to be newer than a copy from any other source.
  58.  
  59.  
  60.  
  61. Michael A. Cooper, University Computing Services, U of Southern California
  62.   UUCP: {sdcrdcf, cit-vax}!oberon!mcooper     BITNET: mcooper@uscvaxq
  63.   ARPA: mcooper@oberon.USC.EDU                PHONE: (213) 743-2957
  64. SHAR_EOF
  65. echo shar: extracting "'Makefile'" '(949 characters)'
  66. if test -f 'Makefile'
  67. then
  68.     echo shar: over-writing existing file "'Makefile'"
  69. fi
  70. cat << \SHAR_EOF > 'Makefile'
  71. #
  72. # $Header: Makefile,v 3.1 87/07/22 09:36:13 mcooper Exp $
  73. #
  74. # Makefile for QTerm
  75. #
  76.  
  77. #
  78. # If you change DIR, run "make reconfig".
  79. #
  80. DIR = /usr/public
  81.  
  82. BIN = $(DIR)/bin
  83. MAN = $(DIR)/man/man1
  84.  
  85. #
  86. # TABFILE should be set to the location you want the qterm table
  87. # file placed in.
  88. #
  89. TABFILE = $(DIR)/lib/qtermtab
  90.  
  91. CONFIGFILES = Makefile qterm.1
  92.  
  93. OBJS = qterm.o
  94. #
  95. # Add "-DUSG5" to $(CFLAGS) below, if your system is Unix System V.
  96. #
  97. CFLAGS = -O -DTABFILE=\"$(TABFILE)\"
  98.  
  99. qterm: $(OBJS) qterm.h
  100.     cc $(CFLAGS) $(OBJS) -o qterm
  101.  
  102. reconfig:
  103.     -@for i in $(CONFIGFILES); do \
  104.                 echo ReConfiguring $$i...;\
  105.         sed "s;/usr/public;$(DIR);g" < $$i > $$i.tmp;\
  106.         mv -f $$i.tmp $$i;\
  107.         done
  108.  
  109. shar:
  110.     shar README Makefile qtermtab qterm.c qterm.h qterm.1 > qterm.shar
  111.  
  112. clean:
  113.     rm -f *.o core log *~ \#* qterm qterm.shar o
  114.  
  115. install: qterm qterm.1 qtermtab
  116.     install qterm $(BIN)
  117.     install -c -m 644 qterm.1 $(MAN)
  118.     install -c -m 644 qtermtab $(TABFILE)
  119. SHAR_EOF
  120. echo shar: extracting "'qtermtab'" '(1556 characters)'
  121. if test -f 'qtermtab'
  122. then
  123.     echo shar: over-writing existing file "'qtermtab'"
  124. fi
  125. cat << \SHAR_EOF > 'qtermtab'
  126. #
  127. # $Header: qtermtab,v 3.0 87/07/01 13:36:30 mcooper Release $
  128. # $Source: /big/src/usc/bin/qterm/RCS/qtermtab,v $
  129. #
  130. # QtermTab - Terminal table for qterm(1).
  131. #
  132. #SendStr ReceiveStr        TermName    FullTermName
  133. #
  134. ^[Z    ^[iBO                 h29         Zenith z29 in zenith mode
  135. ^[Z    ^[/K                  h29         Zenith z29 in zenith mode
  136. ^[Z    ^[[?1;0c             vt100        Base vt100
  137. ^[Z    ^[[?1;1c             vt100       vt100 with STP
  138. ^[Z    ^[[?1;2c             vt100       ANSI/VT100 Clone
  139. ^[Z    ^[[?1;3c             vt100        vt100 with AVO and STP
  140. ^[Z    ^[[?1;4c             vt100        vt100 with GPO
  141. ^[Z    ^[[?1;5c             vt100        vt100 with GPO and STP
  142. ^[Z    ^[[?1;6c             vt100        vt100 with GPO and AVO
  143. ^[Z    ^[[?1;7c             vt100        vt100 with GPO, STP, and AVO
  144. ^[Z    ^[[?6c                vt100           Generic vt100
  145. ^[Z    ^[[?8c                vt100        TeleVideo 970
  146. ^[Z    ^[[0n                 vt100        AT&T Unix PC 7300
  147. ^[Z    ^[[?l;0c             vt100        AT&T Unix PC 7300
  148. ^[Z    ^[[?12c               vt100        Concept from Pro 350/UNIX
  149. ^[Z    ^[[?;c                vt100        Concept From Pro 350/UNIX
  150. ^[Z    ^[[=1;1c             avt-4p-s     Concept with 4 pages memory
  151. ^[Z    ^[[=1;2c             avt-8p-s     Concept with 8 pages memory
  152. ^[Z    ^[/Z                  vt52         Generic vt52
  153. ^[Z    ^[[?10c               la120         DEC Writer III
  154. ^[Z    ^[[?1;11c            cit101e      CIE CIT-101 Enhanced w/Graphics
  155. #^[Z    ^[[?1;11c            xt100+       Northern Tech LANPARSCOPE
  156. ^[Z    ^[[?12;7;0;102c     vt125         DEC Pro 350 in vt125 mode
  157. ^[Z    ^[[?62;1;2;6;7;8;9c     vt220       DEC VT220
  158. ^[Z    ^[[?62;1;4;6;7;8;9;15c    vt200-sb    Microvax II VMS
  159. ^[Z    ^[[62;1;2;6;8c        f220         Freedom 220 DEC clone
  160. ^[Z    ^[[?63;1;2;6;7;8c     tvi9220      TeleVideo 9220
  161. SHAR_EOF
  162. echo shar: extracting "'qterm.c'" '(13185 characters)'
  163. if test -f 'qterm.c'
  164. then
  165.     echo shar: over-writing existing file "'qterm.c'"
  166. fi
  167. cat << \SHAR_EOF > 'qterm.c'
  168. #ifndef lint
  169. static char *RCSid = "$Header: qterm.c,v 3.0 87/06/30 19:07:59 mcooper Release $";
  170. #endif
  171.  
  172. /*
  173.  *------------------------------------------------------------------
  174.  *
  175.  * $Source: /big/src/usc/bin/qterm/RCS/qterm.c,v $
  176.  * $Revision: 3.0 $
  177.  * $Date: 87/06/30 19:07:59 $
  178.  * $State: Release $
  179.  * $Author: mcooper $
  180.  * $Locker:  $
  181.  *
  182.  *------------------------------------------------------------------
  183.  *
  184.  * Michael A. Cooper
  185.  * Research and Development Group
  186.  * University Computing Services 
  187.  * University of Southern California
  188.  * (mcooper@oberon.USC.EDU)
  189.  *
  190.  *------------------------------------------------------------------
  191.  *
  192.  * $Log:    qterm.c,v $
  193.  * Revision 3.0  87/06/30  19:07:59  mcooper
  194.  * Release of version 3.
  195.  * 
  196.  * Revision 2.4  87/04/29  19:28:35  mcooper
  197.  * In readtabfile() we now do special
  198.  * things when opening "file" fails
  199.  * depending on the bequiet flag.
  200.  * 
  201.  * Revision 2.3  87/04/29  13:11:37  mcooper
  202.  * - No more "internal" table.  The master
  203.  *   table is read from a file (TABFILE).
  204.  *   This makes ~/.qterm stuff much cleaner.
  205.  * - Error handling for qtermtab files is
  206.  *   much more informative now.
  207.  * - More things I can't remember.
  208.  * 
  209.  * Revision 2.2  87/03/05  21:01:28  mcooper
  210.  * Fixed system V compiler problem.
  211.  * 
  212.  * Revision 2.1  87/03/01  19:43:22  mcooper
  213.  * Be more intelligent about the size of 
  214.  * the default terminal table.
  215.  * 
  216.  * Revision 2.0  87/03/01  19:20:00  mcooper
  217.  * General cleanup.
  218.  * 
  219.  *------------------------------------------------------------------
  220.  */
  221.  
  222.  
  223. /*
  224.  * qterm - Query Terminal
  225.  *
  226.  * qterm is used to query a terminal to determine the name of the terminal.
  227.  * This is done by sending a fairly universal string "\33Z" to the terminal,
  228.  * reading in a response, and comparing it against a master table of responses
  229.  * and names.  The "name" printed to standard output should be one found in
  230.  * the termcap(5) database.
  231.  *
  232.  * Putting a line in your ".login" file such as:
  233.  *
  234.  *    setenv TERM `qterm`
  235.  *
  236.  * or the following lines in your ".profile" file:
  237.  *
  238.  *    TERM=`qterm`
  239.  *    export TERM
  240.  *
  241.  * will set your terminal type automagically.
  242.  * 
  243.  * If you add a terminal to the master table, please also send me a copy
  244.  * so that I may put it into my version.
  245.  *
  246.  * Michael Cooper
  247.  * ARPA:     mcooper@oberon.USC.EDU
  248.  * UUCP:     {sdcrdcf, cit-vax}!oberon!mcooper
  249.  * BITNET:    mcooper@uscvaxq
  250.  */
  251.  
  252. #include <stdio.h>
  253. #include <pwd.h>
  254. #include <signal.h>
  255. #include <sys/ioctl.h>
  256. #include <setjmp.h>
  257. #ifdef USG5
  258. # include <termio.h>
  259. #else
  260. # include <sys/file.h>
  261. # include <sgtty.h>
  262. #endif
  263.  
  264. #include "qterm.h"
  265.  
  266. int tabtotal = 0;
  267. int has_set = 0;
  268.  
  269. struct qt *compare();
  270. struct qt termtab[MAXTERMS];
  271.  
  272. #ifdef USG5
  273. struct termio _ntty, _otty;
  274. #else
  275. struct sgttyb _tty;
  276. #endif
  277. int _tty_ch = 2;
  278.  
  279.  
  280. static char recvbuf[SIZE];
  281. static char *progname;
  282.  
  283. int debug = FALSE;          /* debug mode */
  284. int aflag = FALSE;          /* alternate string */
  285. int sflag = FALSE;          /* print strings */
  286. int qflag = FALSE;          /* quiet mode */
  287. int fflag = FALSE;          /* use user's own .qterm file */
  288. int Fflag = FALSE;          /* same as above, but don't add our own table */
  289.  
  290. int found = FALSE;
  291. int index = 0;
  292. int finish(), wakeup(), done();
  293.  
  294. char *decode();
  295.  
  296. jmp_buf env;
  297.  
  298. main(argc, argv)
  299. char *argv[];
  300. {
  301.   register int x;
  302.  
  303.   progname = argv[0];
  304.  
  305.   for (x = 1; x < argc; x++) {
  306.     if (argv[x][0] != '-')
  307.       break;
  308.     switch (argv[x][1]) {
  309.       case 'a':
  310.         aflag = TRUE;
  311.         break;
  312.       case 't':
  313.       case 's':
  314.         sflag = TRUE;
  315.         break;
  316.       case 'q':
  317.         qflag = TRUE;
  318.         break;
  319.       case 'f':
  320.         fflag = TRUE;
  321.         break;
  322.       case 'F':
  323.         Fflag = TRUE;
  324.         break;
  325.       case 'd':
  326.         debug = TRUE;
  327.         break;
  328.       default:
  329.         usage();
  330.         exit(1);
  331.     }
  332.   }
  333.  
  334.   setbuf(stdout, 0);
  335.   if(debug)
  336.     setbuf(stderr, 0);
  337.  
  338.   dprintf("[ %s debug mode enabled ]\n\n", progname);
  339.  
  340.   if(!isatty(0))
  341.     fprintf(stderr,"Not a tty.\n");
  342.  
  343. #ifdef USG5
  344.   if(ioctl(_tty_ch, TCGETA, &_otty) < 0)
  345. #else
  346.   if(ioctl(_tty_ch, TIOCGETP, &_tty) < 0)
  347. #endif
  348.   {
  349.     perror("gtty");
  350.     exit(1);
  351.   }
  352. #ifdef USG5
  353.   _ntty = _otty;
  354. #endif
  355.   if(crmode() < 0) {
  356.     perror("crmode");
  357.     exit(1);
  358.   }
  359.   if(noecho() < 0) {
  360.     perror("noecho");
  361.     exit(1);
  362.   }
  363.  
  364.   mktable();
  365.  
  366.   index = 0;
  367.   dprintf("main: we'll do a dotab()\n");
  368.   dotab();
  369.   dprintf("main: dotab done\n");
  370.  
  371.   putc('\r', stderr);
  372.   (void) nocrmode();
  373.   (void) echo();
  374.  
  375.   if(!found) {
  376.     dprintf("end of main\n");
  377.     notrecognized();
  378.   }
  379. }
  380.  
  381. usage()
  382. {
  383.   fprintf(stderr, "usage: %s [ -a ] [ -s ] [ -q ] [ -f ] [ -F ]\n", 
  384.       progname);
  385. }
  386.  
  387. done(s)
  388. int s;
  389. {
  390.   putc('\r', stderr);
  391.   (void) nocrmode();
  392.   (void) echo();
  393.   exit(s);
  394. }
  395.  
  396. /*
  397.  * finish - clean things up.
  398.  */
  399. finish()
  400. {
  401.   dprintf("finish called\n");
  402.  
  403.   putc('\r', stderr);
  404.   (void) nocrmode();
  405.   (void) echo();
  406.  
  407.   if(recvbuf[0] != NULL)
  408.     (void) prinfo(compare(recvbuf, 0, tabtotal), 1);
  409.     
  410.   dprintf("finish done\n");
  411.   if(!found)
  412.     notrecognized();
  413.  
  414.   exit(0);
  415. }
  416.  
  417. prinfo(t, what)
  418. struct qt *t;
  419. int what;
  420. {
  421.   int len = 0;
  422.   int st = FALSE;
  423.  
  424.   dprintf("prinfo startup\n");
  425.  
  426.   if((t != NULL) && (t->qt_termname[0] != NULL) && (recvbuf[0] != NULL)) {
  427.     if(debug || sflag) {
  428.       len = strlen(recvbuf);
  429.       fprintf(stderr, "%s receives %d character%s:", 
  430.         progname, len, (len == 1) ? "" : "s");
  431.       fprintf(stderr, " %s\n", decode(recvbuf));
  432.     }
  433.     if(!qflag)
  434.       if(t->qt_fullname[0] != NULL)
  435.         fprintf(stderr, "Terminal recognized as %s (%s)\n", 
  436.           t->qt_termname, t->qt_fullname);
  437.       else
  438.         fprintf(stderr, "Terminal recognized as %s\n", 
  439.           t->qt_termname);
  440.     printf("%s\n", t->qt_termname);
  441.     found = TRUE;
  442.     done(0);
  443.     /*NOTREACHED*/
  444.   } else {
  445.     found = FALSE;
  446.     if(what) {
  447.       dprintf("prinfo(): doing notrecognized()\n");
  448.       notrecognized();
  449.       done(1);
  450.       /*NOTREACHED*/
  451.     }
  452.   }
  453.  
  454.   dprintf("prinfo done\n");
  455.  
  456.   return(st);
  457. }
  458.  
  459. /*
  460.  * compare - actually compare what we received against the table.
  461.  */
  462. struct qt *
  463. compare(str, start, stop)
  464. char *str;
  465. int start;
  466. int stop;
  467. {
  468.   register int i = 0;
  469.  
  470.   dprintf("compare(%s, %d, %d) startup.\n", decode(str), start, stop);
  471.   alarm(0);
  472.  
  473.   i = start;
  474.   while(i <= stop) {
  475.     dprintf("compare(): tr = '%s'\n", decode(termtab[i].qt_recvstr));
  476.     if(strncmp(str, termtab[i].qt_recvstr, 
  477.       strlen(termtab[i].qt_recvstr)) == 0) {
  478.       found = TRUE;
  479.       return(&termtab[i]);
  480.     }
  481.     ++i;
  482.   }
  483.   found = FALSE;
  484.  
  485.   return(NULL);
  486. }
  487.  
  488. /*
  489.  * getch - read in a character at a time.
  490.  */
  491. getch()
  492. {
  493.   char c;
  494.  
  495.   (void) read(0, &c, 1);
  496.   return(c & CMASK);
  497. }
  498.  
  499. /*
  500.  * decode - print str in a readable fashion
  501.  */
  502. char *
  503. decode(str)
  504. char *str;
  505. {
  506.   char buf[BUFSIZ];
  507.   char tmp[10];
  508.  
  509.   strcpy(buf, "");
  510.   while(*str) {
  511.     if (*str == ESC) {
  512.       strcat(buf, "<esc> ");
  513.     } else if((*str <= 33) || (*str >= 127)) {
  514.       sprintf(tmp,"\\%o ", *str);
  515.       strcat(buf, tmp);
  516.     } else {
  517.       sprintf(tmp,"%c ", *str);
  518.       strcat(buf, tmp);
  519.     }
  520.     *++str;
  521.   }
  522.   return(buf);
  523. }
  524.  
  525. mktable()
  526. {
  527.   char file[BUFSIZ];
  528.   struct passwd *pwd;
  529.   char *home;
  530.  
  531.   dprintf("[ initilizing term table... ]\n");
  532.  
  533.   if(fflag) {
  534.     /*
  535.      * Try and read the user's own table
  536.      */
  537.     if((home = (char *) getenv("HOME")) == NULL) {
  538.       if((pwd = (struct passwd *) getpwuid(getuid())) == NULL) {
  539.     fprintf(stderr, "Who the hell are you????\n");
  540.     exit(1);
  541.       }
  542.       home = pwd->pw_dir;
  543.     }
  544.     dprintf("home = '%s'\n", home);
  545.     sprintf(file, "%s/%s", home, STRFILE);
  546.     dprintf("strfile = '%s'\n", file);
  547.  
  548.     (void) readtabfile(file, TRUE);
  549.   }
  550.  
  551.   if(!Fflag)
  552.     (void) readtabfile(TABFILE, FALSE);
  553.  
  554.   dprintf("termtab total  = %d\n", tabtotal);
  555.   dprintf("[ mktable done ]\n");
  556. }
  557.  
  558. readtabfile(file, bequiet)
  559. char *file;
  560. int bequiet;
  561. {
  562.   static int i = 0, line;
  563.   char lbuf[4][BUFSIZ];
  564.   char buf[BUFSIZ];
  565.   FILE *fd, *fopen();
  566.   char *msg, *fixctl();
  567.   int iserr = 0;
  568.  
  569.   if((fd = fopen(file, "r")) == NULL) {
  570.     if(bequiet)
  571.       return(-1);
  572.     perror(file);
  573.     done(1);
  574.   }
  575.  
  576.   line = 0;
  577.   while(fgets(buf, sizeof(buf), fd) && i < MAXTERMS) {
  578.     ++line;
  579.     
  580.     if(buf[0] == '#' || buf[0] == '\n')
  581.       continue;
  582.     
  583.     lbuf[0][0] = NULL;
  584.     lbuf[1][0] = NULL;
  585.     lbuf[2][0] = NULL;
  586.     lbuf[3][0] = NULL;
  587.     
  588.     (void) sscanf(buf, "%s%s%s\t%[^\n]", 
  589.           lbuf[0], lbuf[1], lbuf[2], lbuf[3]);
  590.     if(lbuf[0][0] == NULL)
  591.       continue;
  592.     if(lbuf[1][0] == NULL) {
  593.       iserr = TRUE;
  594.       msg = "receive string";
  595.     }
  596.     if(lbuf[2][0] == NULL) {
  597.       iserr = TRUE;
  598.       msg = "terminal name";
  599.     }
  600.     if(iserr) {
  601.       fprintf(stderr, "Line %d of %s: Error parsing %s.\n", 
  602.           line, file, msg);
  603.       done(1);
  604.       /* NOTREACHED */
  605.     }
  606.     if(aflag)
  607.       (void) strcpy(termtab[i].qt_sendstr, fixctl(ALTSEND));
  608.     else
  609.       (void) strcpy(termtab[i].qt_sendstr, fixctl(lbuf[0]));
  610.     (void) strcpy(termtab[i].qt_recvstr, fixctl(lbuf[1]));
  611.     (void) strcpy(termtab[i].qt_termname, lbuf[2]);
  612.     (void) strcpy(termtab[i].qt_fullname, lbuf[3]);
  613.     
  614.     dprintf("entry %d:\n", i);
  615.     dprintf("qt_sendstr = %s\n", decode(termtab[i].qt_sendstr));
  616.     dprintf("qt_recvstr = %s\n", decode(termtab[i].qt_recvstr));
  617.     dprintf("qt_termname = '%s'\n", termtab[i].qt_termname);
  618.     dprintf("qt_fullname = '%s'\n", termtab[i].qt_fullname);
  619.     
  620.     ++i;
  621.   }
  622.  
  623.   tabtotal = i;
  624.  
  625.   return(0);
  626. }
  627.  
  628. listen(q)
  629. struct qt *q;
  630. {
  631.   register int i;
  632.   register char c;
  633.   char end, begin;
  634.  
  635.   dprintf("listen startup\n");
  636.   alarm(0);
  637.  
  638.   dprintf("listen: listening for '%s'\n", decode(q->qt_recvstr));
  639.  
  640.   if (q->qt_recvstr[0] == NULL) {
  641.     begin = ESC;
  642.     end = 'c';
  643.   } else {
  644.     begin = q->qt_recvstr[0];
  645.     end = q->qt_recvstr[strlen(q->qt_recvstr)-1];
  646.   }
  647.  
  648.   dprintf("listen: read initial character...\n");
  649.   if(setjmp(env)) {
  650.     dprintf("listen: setjmp TRUE\n");
  651.     if(found)
  652.       done();
  653.     ++index;
  654.     (void) fflush(stdin);
  655.     dprintf("listen: dotab()\n");
  656.     dotab();
  657.   } else {
  658.     dprintf("listen: setjmp FALSE...set alarm\n");
  659.     signal(SIGALRM, wakeup);
  660.     alarm(WAIT);
  661.     dprintf("listen: read char\n");
  662.     recvbuf[0] = getch();
  663.     alarm(0);
  664.     dprintf("recvbuf[0] = '\\%o'\n", recvbuf[0]);
  665.  
  666.   }
  667.   i = 0;
  668.   if(recvbuf[0] == begin) {
  669.     dprintf("listen begin\n");
  670.     while(c != end) {
  671.       if(setjmp(env))  {
  672.         dprintf("listen: setjmp (2) return\n");
  673.         return;
  674.       } else {
  675.         signal(SIGALRM, wakeup);
  676.         alarm(WAIT);
  677.         dprintf("listen: read (2) char\n");
  678.         c = getch();
  679.         alarm(0);
  680.         dprintf("recvbuf[0] = '\\%o'\n", recvbuf[0]);
  681.       }
  682.       recvbuf[++i] = c;
  683.     }
  684.     if(debug)
  685.       fprintf(stderr,"\n[ Received terminator. ]\n");
  686.   } else {
  687.     dprintf("listen: Not Recognized.  exiting...\n");
  688.     notrecognized();
  689.     putc('\r',stderr);
  690.     (void) nocrmode();
  691.     (void) echo();
  692.     exit(1);
  693.   }
  694.   dprintf("listen done\n");
  695. }
  696.  
  697. notrecognized()
  698. {
  699.   if(!qflag)
  700.     fprintf(stderr, 
  701.       "Terminal NOT recognized - defaults to \"dumb\".\n");
  702.   puts("dumb");
  703. }
  704.  
  705. wakeup()
  706. {
  707.   dprintf("wakeup called\n");
  708.   longjmp(env, 1);
  709.   dprintf("wakeUP: done\n");
  710. }
  711.  
  712. dotab()
  713. {
  714.   int wakeup();
  715.   int st = FALSE;
  716.   static int firsttime = TRUE;
  717.  
  718.   dprintf("dotab startup\n");
  719.   dprintf("index = %d\n", index);
  720.  
  721.   if(index > tabtotal) {
  722.     /*
  723.      * if we haven't reset things yet, do so.
  724.      * now try the internal tables if the user's
  725.      * tables failed.
  726.      */
  727.     if(!has_set)  {
  728.       index = 0;
  729.       has_set = 1;
  730.       dprintf("dotab(): has_set now true.\n");
  731.       dotab();
  732.     }
  733.     dprintf("dotab(): index > tabtotal\n");
  734.     finish();
  735.   }
  736.   if(!found || fflag) {
  737.     while(!found && termtab[index].qt_sendstr[0] != NULL && !st) {
  738.       dprintf("dotab: termtab PASS %d\n", index);
  739.       dprintf("dotab: sending str %s\n", 
  740.         decode(termtab[index].qt_sendstr));
  741.       (void) fflush(stdin);
  742.  
  743.       if(firsttime || strncmp(termtab[index].qt_sendstr, 
  744.         termtab[index-1].qt_sendstr,
  745.         strlen(termtab[index].qt_sendstr))) {
  746.  
  747.         firsttime = FALSE;
  748.         dprintf("dotab(): sendstr's didn't match.\n");
  749.         dprintf("dotab: str1 %s\n", decode(termtab[index].qt_sendstr));
  750.         dprintf("dotab: str2 %s\n", decode(termtab[index-1].qt_sendstr));
  751.  
  752.         fprintf(stderr, termtab[index].qt_sendstr);
  753.         (void) fflush(stdout);
  754.         (void) fflush(stderr);
  755.  
  756.         (void) listen(&termtab[index]);
  757.       } else {
  758.         dprintf("dotab(): sendstr's DID match.  No str sent.\n");
  759.         dprintf("dotab: str1 %s\n", decode(termtab[index].qt_sendstr));
  760.         dprintf("dotab: str2 %s\n", decode(termtab[index-1].qt_sendstr));
  761.       }
  762.  
  763.       firsttime = FALSE;
  764.       dprintf("dotab(): recbuf = '%s'\n", decode(recvbuf));
  765.       dprintf("dotab(): qt_rec = '%s'\n", decode(termtab[index].qt_recvstr));
  766.  
  767.       st = prinfo(compare(recvbuf, 0, tabtotal), FALSE);
  768.  
  769.       dprintf("st = %d\n", st);
  770.  
  771.       ++index;
  772.     }
  773.   }
  774.  
  775.   if(!found) {
  776.     dprintf("dotab: failed.\n");
  777.     notrecognized();
  778.   }
  779.  
  780.   done();
  781. }
  782.  
  783. char *
  784. fixctl(str)
  785. char *str;
  786. {
  787.   register int i;
  788.   char buf[BUFSIZ];
  789.  
  790.   i = 0;
  791.   while(*str) {
  792.     if(*str == '^')
  793.       buf[i++] = *++str & 037;
  794.     else
  795.       buf[i++] = *str;
  796.     *++str;
  797.   }
  798.   buf[i] = NULL;
  799.   return(buf);
  800. }
  801. SHAR_EOF
  802. echo shar: extracting "'qterm.h'" '(2544 characters)'
  803. if test -f 'qterm.h'
  804. then
  805.     echo shar: over-writing existing file "'qterm.h'"
  806. fi
  807. cat << \SHAR_EOF > 'qterm.h'
  808. /*
  809.  * $Header: qterm.h,v 3.0 87/06/30 19:09:04 mcooper Release $
  810.  *------------------------------------------------------------------
  811.  *
  812.  * $Source: /big/src/usc/bin/qterm/RCS/qterm.h,v $
  813.  * $Revision: 3.0 $
  814.  * $Date: 87/06/30 19:09:04 $
  815.  * $State: Release $
  816.  * $Author: mcooper $
  817.  * $Locker:  $
  818.  *
  819.  *------------------------------------------------------------------
  820.  *
  821.  * Michael A. Cooper
  822.  * Research and Development Group
  823.  * University Computing Services 
  824.  * University of Southern California
  825.  * (mcooper@oberon.USC.EDU)
  826.  *
  827.  *------------------------------------------------------------------
  828.  * $Log:    qterm.h,v $
  829.  * Revision 3.0  87/06/30  19:09:04  mcooper
  830.  * Release of version 3.
  831.  * 
  832.  * Revision 2.4  87/06/30  19:02:28  mcooper
  833.  * WAIT changed to 2 for slow systems.
  834.  * 
  835.  *------------------------------------------------------------------
  836.  */
  837.  
  838.  
  839.  
  840. #ifndef TABFILE
  841. # define TABFILE   "/usr/local/lib/qtermtab"
  842. #endif
  843.  
  844. #define ALTSEND    "\033[c"            /* alternate string */
  845. #define STRFILE    ".qterm"            /* file containing terminal strings */
  846.  
  847. #define WAIT       2                   /* Number of seconds for alarms */
  848. #define MAXTERMS   50                  /* Maximum # of terminals for qterm */
  849.  
  850. #define SIZE      512
  851. #define CMASK     0377
  852. #define ESC       '\033'
  853.  
  854. #define TRUE       1
  855. #define FALSE      0
  856.  
  857. #ifdef USG5
  858. # define crmode()     (_ntty.c_lflag &= ~ICANON,\
  859.                _ntty.c_cc[VMIN] = 1, _ntty.c_cc[VTIME] = 0,\
  860.                ioctl(_tty_ch, TCSETAF, &_ntty))
  861. # define nocrmode()   (_ntty.c_lflag |= ICANON,\
  862.                _ntty.c_cc[VMIN] = _otty.c_cc[VMIN],\
  863.                _ntty.c_cc[VTIME] = _otty.c_cc[VTIME],\
  864.                ioctl(_tty_ch, TCSETAF, &_ntty))
  865. # define echo()       (_ntty.c_lflag |= ECHO,\
  866.                ioctl(_tty_ch, TCSETAF, &_ntty))
  867. # define noecho()     (_ntty.c_lflag &= ~ECHO,\
  868.                ioctl(_tty_ch, TCSETAF, &_ntty))
  869. #else
  870. # define crmode()     (_tty.sg_flags |= CBREAK,\
  871.                ioctl(_tty_ch, TIOCSETP, &_tty))
  872. # define nocrmode()   (_tty.sg_flags &= ~CBREAK,\
  873.                ioctl(_tty_ch, TIOCSETP, &_tty))
  874. # define echo()       (_tty.sg_flags |= ECHO,   \
  875.                ioctl(_tty_ch, TIOCSETP, &_tty))
  876. # define noecho()     (_tty.sg_flags &= ~ECHO,  \
  877.                ioctl(_tty_ch, TIOCSETP, &_tty))
  878. #endif
  879.  
  880. #define dprintf    if(debug)printf
  881.  
  882. struct qt {
  883.   char  qt_sendstr[BUFSIZ];     /* String to send to terminal */
  884.   char  qt_recvstr[BUFSIZ];     /* String expected in response */
  885.   char  qt_termname[BUFSIZ];    /* Terminal name */
  886.   char  qt_fullname[BUFSIZ];    /* Full terminal name & description */
  887. };
  888. SHAR_EOF
  889. echo shar: extracting "'qterm.1'" '(3608 characters)'
  890. if test -f 'qterm.1'
  891. then
  892.     echo shar: over-writing existing file "'qterm.1'"
  893. fi
  894. cat << \SHAR_EOF > 'qterm.1'
  895. .\"
  896. .\" $Header: qterm.1,v 3.0 87/06/30 19:10:08 mcooper Release $
  897. .\"
  898. .TH QTERM 1 "29 April 1987"
  899. .ds ]W USC-UCS
  900. .SH NAME
  901. qterm \- Query Terminal
  902. .SH SYNOPSIS
  903. qterm 
  904. [
  905. .B \-a
  906. ]
  907. [
  908. .B \-f
  909. ]
  910. [
  911. .B \-F
  912. ]
  913. [
  914. .B \-s
  915. ]
  916. [
  917. .B \-q
  918. ]
  919. .SH DESCRIPTION
  920. .I Qterm
  921. is used to query a terminal to determine its name.
  922. This is done by sending a special sequence to the terminal,
  923. reading in a response, and comparing it against a master table of possible
  924. responses.
  925. The ``name'' printed to standard output should be one found in
  926. the
  927. .I termcap(5) 
  928. database.
  929. .PP
  930. For 
  931. .I csh(1) 
  932. users,
  933. putting a line in your 
  934. .I .login 
  935. file such as:
  936. .sp 1
  937. .in +.5i
  938. setenv TERM `qterm`
  939. .in -.5i
  940. .sp 1
  941. should automagically set your terminal type.
  942. For 
  943. .I sh(1)
  944. users, putting these lines in your 
  945. .I .profile 
  946. file should set your terminal type:
  947. .sp 1
  948. .in +.5i
  949. TERM=`qterm`
  950. .br
  951. export TERM
  952. .in -.5i
  953. .sp 1
  954. .SH OPTIONS
  955. .IP \-a
  956. Use the alternate string ``<ESCAPE>[c'' when asking the terminal to
  957. identify itself.  This string is recognized by most ANSI compatible
  958. terminals.
  959. .IP \-f
  960. If the file
  961. .B $HOME/.qterm
  962. is present, it's contents are scanned to produce information for
  963. querying terminals.  In this way, a user may setup different values
  964. for certain terminals.
  965. After the contents of this file have been scanned, 
  966. .I qterm
  967. proceeds to query the terminal with the information provided.
  968. If an un-intelligable response is received (or non at all), 
  969. .I qterm
  970. will proceed to use its own information to determine the terminal
  971. type.
  972. .IP \-F
  973. Same as \-f except that the standard 
  974. .I qterm
  975. table is not scanned; only the user's 
  976. .B $HOME/.qterm
  977. file is used.
  978. .IP \-s
  979. Display the response received from
  980. the terminal in a ``nice'' fashion.
  981. .IP \-q
  982. Be ``quiet'' and only print the terminal name to standard
  983. output.
  984. .SH "QTERMTAB"
  985. The format of the file
  986. $HOME/.qterm
  987. and 
  988. .I qterm's
  989. master file
  990. .I /usr/public/lib/qtermtab,
  991. consists of four fields each seperated by white space (tabs and/or spaces).
  992. The first field is the string that should be used to query the terminal.
  993. The second field is the string to expect in response to the query.
  994. The third field is the terminal name (compatible with 
  995. .I termcap(5))
  996. to print to standard output.
  997. The fourth field is optional and may contain a description of the exact
  998. manufacturer and model name of the terminal to be used in a message
  999. printed to standard error.
  1000. .PP
  1001. Blank lines or lines starting with the character ``#''
  1002. are ignored and may be used as comment lines.
  1003. A character preceeded by a ``^'' is taken to mean the 
  1004. .I control
  1005. character.  (i.e. ``^['' is interpretted as an <ESCAPE>).
  1006. .PP
  1007. Below is a sample file:
  1008. .sp 2
  1009. .nf
  1010.     #
  1011.     # QTerm File
  1012.     #
  1013.     ^[Z\0\0\0\0\0^[[?1;1c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with STP
  1014.     ^[Z\0\0\0\0\0^[[?1;2c\0\0\0\0\0vt100\0\0\0\0\0ANSI/VT100 Clone
  1015.     ^[Z\0\0\0\0\0^[[?1;3c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with AVO and STP
  1016.     ^[Z\0\0\0\0\0^[[?1;4c\0\0\0\0\0vt100\0\0\0\0\0A vt100 with GPO
  1017.     ^[Z\0\0\0\0\0^[iBO\0\0\0\0\0\0\0\0z29\0\0\0\0\0\0\0Zenith in Zenith Mode
  1018. .fi
  1019. .sp
  1020. .SH AUTHOR
  1021. Michael A. Cooper, 
  1022. .br
  1023. University Computing Services, 
  1024. .br
  1025. University of Southern California.
  1026. .SH FILES
  1027. .ta \w'/usr/public/lib/qtermtab\ \ \ 'u
  1028. /usr/public/lib/qtermtab    \- Master table
  1029. .br
  1030. $HOME/.qterm    \- User's table
  1031. .br
  1032. /etc/termcap    \- termcap(5) database
  1033. .SH SEE ALSO
  1034. csh(1), sh(1), termcap(5)
  1035. .SH DIAGNOSTICS
  1036. .IP "\fITerminal not recognized - defaults to dumb.\fP"
  1037. .I QTerm
  1038. did not receive a response from the terminal, or the response
  1039. did not match any that 
  1040. .I qterm 
  1041. has stored internally.  Use the \-s option to check to see which
  1042. is the case.
  1043. .SH BUGS
  1044. Many terminals do not send a response at all.
  1045. SHAR_EOF
  1046. #    End of shell archive
  1047. exit 0
  1048. -- 
  1049.  
  1050. Rich $alz            "Anger is an energy"
  1051. Cronus Project, BBN Labs    rsalz@bbn.com
  1052. Moderator, comp.sources.unix    sources@uunet.uu.net
  1053.